#include "ConcurrentMemoryPool.h"

void* ConcurrentMemoryPool::ConcurrentAlloc(size_t size)
{
    if(size > MAX_BYTES)//大于256kb的申请，直接向页缓存申请
    {
        size_t alignPageSize = SizeClass::RoundUp(size);
        size_t numPage = alignPageSize >> PAGE_SHIFT;
        PageCache::GetInstance()->_pageMutex.lock();
        Span* span = PageCache::GetInstance()->NewSpan(numPage);
        PageCache::GetInstance()->_pageMutex.unlock();
        span->_objSize = size;
        void* ptr = (void*)(span->_pageId << PAGE_SHIFT);
        return ptr;
    }
    else
    { 
        //通过TLS，每个线程无锁获取专属对象
        if(pTLSThreadCache == nullptr)
        {
            //声明为static，保持全局只有一个
            static std::mutex threadMutex;
            static ObjectPool<ThreadCache> threadPool;
            threadMutex.lock();
            pTLSThreadCache = threadPool.New();//如果没有thread cache，就new一个出来
            threadMutex.unlock();
        }
        return pTLSThreadCache->Allocate(size);
    }
}

void ConcurrentMemoryPool::ConcurrentFree(void * ptr)
{
    Span* span = PageCache::GetInstance()->MapObjectToSpan(ptr);//获取指针对应的span
    size_t size = span->_objSize;//获取span中内存块的大小即归还内存的大小
    if(size > MAX_BYTES)//如果大于256kb，直接释放回page cache
    {
        PageCache::GetInstance()->_pageMutex.lock();
        PageCache::GetInstance()->ReleaseSpanToPageCache(span);
        PageCache::GetInstance()->_pageMutex.unlock();
    }
    else//小于256kb则归还给thread cache
    {
        assert(pTLSThreadCache);
        pTLSThreadCache->Freelocate(ptr, size);
    }
}